package com.jgame.secondarymarket.domain.auth.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 定义客户端类型
 *
 * @title: OAuthClientDetailsService
 * @Author Wangsj
 * @Date: 2021/7/27
 */
@Component
public class OAuthClientDetailsService implements ClientDetailsService {

    /**
     * 客户端ID
     * 这里的客户端就是指本项目的前端代码
     */
    private static final String CLIENT_ID = "store_frontend";
    /**
     * 客户端密钥
     * 在OAuth2协议中，ID是可以公开的，密钥应当保密，密钥用以证明当前申请授权的客户端是未被冒充的
     */
    private static final String CLIENT_SECRET = "store_secret";


    @Autowired
    private PasswordEncoder passwordEncoder;

    private ClientDetailsService clientDetailsService;

    /**
     * 构造密码授权模式
     * <p>
     * 授权Endpoint示例：
     * /oauth/token?grant_type=password & username=#USER# & password=#PWD# & client_id=bookstore_frontend & client_secret=bookstore_secret
     * 刷新令牌Endpoint示例：
     * /oauth/token?grant_type=refresh_token & refresh_token=#REFRESH_TOKEN# & client_id=bookstore_frontend & client_secret=bookstore_secret
     */
    @PostConstruct
    public void init() throws Exception {
        InMemoryClientDetailsServiceBuilder builder = new InMemoryClientDetailsServiceBuilder();
        // 提供客户端ID和密钥，并指定该客户端支持密码授权、刷新令牌两种访问类型
        builder.withClient(CLIENT_ID)
                .secret(passwordEncoder.encode(CLIENT_SECRET))
                .scopes("all", "read", "write")
                .authorizedGrantTypes("password", "refresh_token");
        clientDetailsService = builder.build();
    }

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
        return clientDetailsService.loadClientByClientId(clientId);
    }
}
